home *** CD-ROM | disk | FTP | other *** search
/ PsL Monthly 1993 December / PSL Monthly Shareware CD-ROM (December 1993).iso / prgmming / dos / pascal / exarray.com / XGENHEAP.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1989-08-19  |  6.2 KB  |  219 lines

  1. Unit XGenHeap; {ExtendedArray-Based Generic Heaps}
  2. {$R-,O+,S-}
  3. {$B-}
  4.     {*MUST* ensure Short-Circuit Boolean Evaluation!}
  5.  
  6. {Introduces the Generic Heap variant of the ExtendedArray Object}
  7.  
  8. { XGenericHeaps are indexed 1..MaxElements, rather then 0..MaxElements-1 }
  9.  
  10. { XGenericHeaps are bigger than their MaxArray based cousins, but otherwise }
  11. { completely interchangeable.  NOTE: Even though Copy is implemented, I do  }
  12. { NOT anticipate it often being possible to use it!                         }
  13.  
  14. { PERFORMANCE NOTES: SiftUp works quite nicely, but sad to say SiftDown is }
  15. {                    REALLY BAD.  Thus, sorting performance degrades quite }
  16. {                    rapidly in proportion to the number of Lobes on Disk. }
  17. {                    See comments in XHeaps for more.                      }
  18.  
  19. INTERFACE
  20.  
  21. Uses ExtArray,SrtFuncs,FlexPntr;
  22.  
  23. Type
  24.   XGenericHeap = Object (ExtendedArray)
  25.  
  26.                 Greater : SortFunc;
  27.  
  28.                 Procedure Init (MaxElements : LongInt; ElementSize : Word;
  29.                                 GreaterFunc : SortFunc);
  30.  
  31.                 { Accept, Retrieve, and Swap are only redefined to      }
  32.                 { implement the 1..MaxElement indexing needed for Heaps }
  33.  
  34.                 Procedure Accept (Var El; Index : LongInt; Size : Word);
  35.  
  36.                 Procedure Retrieve (Var El; Index : LongInt; Size : Word);
  37.  
  38.                 Procedure Swap (I,J : LongInt);
  39.  
  40.                 Procedure SiftDown (I,J : LongInt);
  41.  
  42.                                    { While I can think of No reason to  }
  43.                                    { Use SiftDown externally, there may }
  44.                                    { be a reason, so I have exported it }
  45.  
  46.                 Procedure SiftUp (Var El; Index : LongInt; Size : Word);
  47.  
  48.                                  { SiftUp can be used in place of Accept }
  49.                                  { In order to Create/Maintain a Heap as }
  50.                                  { a Heap while adding elements, thus    }
  51.                                  { allowing the use of Sort instead of   }
  52.                                  { HeapSort which structures a Heap by   }
  53.                                  { using BuildHeap.                      }
  54.  
  55.                 Procedure BuildHeap;
  56.  
  57.                                  { Creates the Heap structure from }
  58.                                  { the ground up.                  }
  59.  
  60.                 Procedure Sort;
  61.  
  62.                           { Sorts a Heap into Ascending order    }
  63.                           { Assumes HEAP is built or maintained. }
  64.  
  65.                 Procedure ChangeSort (NewSort : SortFunc);
  66.  
  67.                           { Permits the changing of sorting methods   }
  68.                           { such as might be required for sorting     }
  69.                           { records by a different field, for example }
  70.  
  71.                 { NOTE: This will require use of HeapSort to re-sort. }
  72.  
  73.                 Procedure HeapSort;
  74.  
  75.                           { Sorts a Heap into Ascending order     }
  76.                           { Assumes nothing about Heap structure. }
  77.  
  78.                 Procedure Copy (From : XGenericHeap);
  79.  
  80.                           { Target Heap *MUST* be initialized  }
  81.                           { to EXACTLY same parameters as From }
  82.  
  83.              End;
  84.  
  85.  
  86. IMPLEMENTATION
  87.  
  88. Procedure XGenericHeap.Init;
  89. Begin
  90.   Greater := GreaterFunc;
  91.   ExtendedArray.ManualInit (MaxElements,ElementSize,56000)
  92. End;
  93.  
  94. Procedure XGenericHeap.Accept (Var El; Index : LongInt; Size : Word);
  95. Begin
  96.   ExtendedArray.Accept (El,Index-1,Size)
  97. End;
  98.  
  99. Procedure XGenericHeap.Retrieve (Var El; Index : LongInt; Size : Word);
  100. Begin
  101.   ExtendedArray.Retrieve (El,Index-1,Size);
  102. End;
  103.  
  104. Procedure XGenericHeap.Swap (I,J : LongInt);
  105. Begin
  106.   ExtendedArray.Swap (I-1,J-1)
  107. End;
  108.  
  109. Procedure XGenericHeap.SiftDown (I,J : LongInt);
  110. Var
  111.   K     : LongInt;
  112.   T1,T2 : FlexPtr;
  113. Begin
  114.   If I <= J Div 2  {J = "HeapLength"}
  115.     Then
  116.       Begin
  117.         GetMem (T1,SizeOf(FlexCount)+ElemSize);
  118.         GetMem (T2,SizeOf(FlexCount)+ElemSize);
  119.         If (1+2*I) > J
  120.           Then
  121.             K := 2*I
  122.           Else
  123.             Begin
  124.               Retrieve (T1^.Flex,2*I,ElemSize);
  125.               Retrieve (T2^.Flex,1+2*I,ElemSize);
  126.               If (Greater (T1^.Flex,T2^.Flex))
  127.                 Then
  128.                   K := 2*I
  129.                 Else
  130.                   K := 1+2*I
  131.             End;
  132.         Retrieve (T1^.Flex,K,ElemSize);
  133.         Retrieve (T2^.Flex,I,ElemSize);
  134.         If (Greater (T1^.Flex,T2^.Flex))
  135.           Then
  136.             Begin
  137.               Swap (K,I);
  138.               SiftDown (K,J)
  139.             End;
  140.         FreeMem (T1,SizeOf(FlexCount)+ElemSize);
  141.         FreeMem (T2,SizeOf(FlexCount)+ElemSize)
  142.       End
  143. End;
  144.  
  145. Procedure XGenericHeap.SiftUp (Var El; Index : LongInt; Size : Word);
  146. Var
  147.   J,K   : LongInt;
  148.   T1,T2 : FlexPtr;
  149. Begin
  150.   Accept (El,Index,Size);
  151.   If Index >= 2 Then
  152.     Begin
  153.       GetMem (T1,SizeOf(FlexCount)+ElemSize);
  154.       GetMem (T2,SizeOf(FlexCount)+ElemSize);
  155.       K := Index;
  156.       J := K Div 2;
  157.       Retrieve (T1^.Flex,K,ElemSize);
  158.       Retrieve (T2^.Flex,J,ElemSize);
  159.       While ((J > 0) and (Greater (T1^.Flex,T2^.Flex))) do
  160.         Begin
  161.           Swap (K,J);
  162.           K := J;
  163.           J := K Div 2;
  164.           If J > 0
  165.             Then
  166.               Begin
  167.                 Retrieve (T1^.Flex,K,ElemSize);
  168.                 Retrieve (T2^.Flex,J,ElemSize)
  169.               End
  170.         End;
  171.       FreeMem (T1,SizeOf(FlexCount)+ElemSize);
  172.       FreeMem (T2,SizeOf(FlexCount)+ElemSize)
  173.     End
  174. End;
  175.  
  176. Procedure XGenericHeap.BuildHeap;
  177. Var
  178.   I: LongInt;
  179. Begin
  180.   For I := MaxEl Div 2 DownTo 1 do SiftDown (I,MaxEl)
  181. End;
  182.  
  183. Procedure XGenericHeap.ChangeSort (NewSort : SortFunc);
  184. Begin
  185.   Greater := NewSort
  186. End;
  187.  
  188. Procedure XGenericHeap.Sort;  {Assumes HEAP is built or maintained}
  189. Var
  190.   I : LongInt;
  191. Begin
  192.   For I := MaxEl DownTo 2 do
  193.     Begin
  194.       Swap (1,I);
  195.  
  196.       GoToXY (12,13);
  197.       Write (100000-I);
  198.       ClrEol;
  199.  
  200.       SiftDown (1,I-1)
  201.     End
  202. End;
  203.  
  204. Procedure XGenericHeap.HeapSort;
  205. Var
  206.   I : LongInt;
  207. Begin
  208.   BuildHeap;
  209.   Sort
  210. End;
  211.  
  212. Procedure XGenericHeap.Copy;
  213. Begin
  214.   Greater := From.Greater;
  215.   ExtendedArray.Copy (From)
  216. End;
  217.  
  218. BEGIN
  219. END.